﻿
using System;
using System.Collections;
using System.Data;
using System.Net;
using System.Text;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Core;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Convertor;

/// <summary>
/// <seealso cref="string"/> 转换器
/// </summary>
public class StringConvertor : AllowNullConvertor<string>,
    IFrom<Type, string>,
    IFrom<byte[], string>,
    IFrom<bool, string>,
    IFrom<Uri, string>,
    IFrom<StringBuilder, string>,
    IFrom<IPAddress, string>,
    IFrom<object, string>,
    IFrom<IFormattable, string>,
    IFrom<IConvertible, string>,
    IFrom<IEnumerator, string>,
    IFrom<IEnumerable, string>
{
    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, Type input) => input.GetFriendlyName();

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, IConvertible input) => new(context.Settings.Format(input));

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, byte[] input) => (context.Settings.Encoding ?? Encoding.UTF8).GetString(input);

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, bool input) => input ? "true" : "false";

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, IEnumerable input) => context.Settings.StringSerializer?.ToString(input) ?? From(context, input.GetEnumerator());

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, object input) => context.Settings.StringSerializer?.ToString(input) ?? input.ToString();

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, Uri input) => input?.ToString();

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, StringBuilder input) => input?.ToString();

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, IEnumerator input)
    {
        if (input is null || !input.MoveNext())
        {
            return default;
        }
        var s = context.Convert<string>(input.Current);
        if (!s.Success)
        {
            return s;
        }

        var sb = new StringBuilder(s.Value);
        while (input.MoveNext())
        {
            s = context.Convert<string>(input.Current);
            if (!s.Success)
            {
                return s;
            }
            _ = sb.Append(context.Settings.StringSeparator?.First ?? ",");
            _ = sb.Append(s.Value);

        }
        return sb.ToString();
    }

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, IPAddress input) => input.ToString();

    /// <inheritdoc/>
    public ConvertResult<string> From(IConvertContext context, IFormattable input) => context.Settings.Format(input);
}
